跳到主要内容

C# 基本语法学习

参考资料 菜鸟教程 C# 基本语法

配置插件查看源码

用 IDEA 写 Java写习惯了,平时写代码时总是习惯性的查看源码,但是到了 VS2019 这里无法直接看到源码,只能看到函数的定义,这点实在是有点不爽,这里来配置一下环境,使之能直接查看源码

如果使用的是 Resharper 这样设置就行了

隐式转换

在学习 Unity 时看到这个 static implicit operator 有点好奇它是什么,实际上它就是一个隐式转换用的语法

使用如下

public struct Vector2 {
// Vector3 转换成 Vector2
public static implicit operator Vector2(Vector3 v){
return new Vector2(v.x,v.y);
}

// Vector2 转换成 Vector3
public static implicit operator Vector3(Vector2 v){
return new Vector3(v.x,v.y,0);
}
}

所以这个就是 RaycastHit2D 转换成 bool

public static implicit operator bool(RaycastHit2D hit);

C# 一些重要的功能

  • 布尔条件(Boolean Conditions)
  • 自动垃圾回收(Automatic Garbage Collection)
  • 标准库(Standard Library)
  • 组件版本(Assembly Versioning)
  • 属性(Properties)和事件(Events)
  • 委托(Delegates)和事件管理(Events Management)
  • 易于使用的泛型(Generics)
  • 索引器(Indexers)
  • 条件编译(Conditional Compilation)
  • 简单的多线程(Multithreading)
  • LINQ 和 Lambda 表达式
  • 集成 Windows

字符串(String)类型

字符串(String)类型 允许您给变量分配任何字符串值。字符串(String)类型是 System.String 类的别名。它是从对象(Object)类型派生的。字符串(String)类型的值可以通过两种形式进行分配:引号和 @ 引号。

例如:

String str = "example.com";

一个 @ 引号字符串:

@"example.com";

C# string 字符串的前面可以加 @(称作"逐字字符串")将转义字符(\)当作普通字符对待,比如:

string str = @"C:\Windows";

等价于:

string str = "C:\\Windows";

@ 字符串中可以任意换行,换行符及缩进空格都计算在字符串长度之内。

string str = @"<script type=""text/javascript"">
<!--
-->
</script>";

指针类型(Pointer types)

指针类型变量存储另一种类型的内存地址。C# 中的指针与 C 或 C++ 中的指针有相同的功能。

声明指针类型的语法:

type* identifier;

例如:

char* cptr;
int* iptr;

C# 结构体(Struct)

在 C# 中,结构体是值类型数据结构。

它使得一个单一变量可以存储各种数据类型的相关数据。

struct 关键字用于创建结构体。

struct Books
{
public string title;
public string author;
public string subject;
public int book_id;
};

在 C# 中的结构与传统的 C 或 C++ 中的结构不同。C# 中的结构有以下特点:

  • 结构可带有方法、字段、索引、属性、运算符方法和事件。
  • 结构可定义构造函数,但不能定义析构函数。但是,不能为结构定义无参构造函数。无参构造函数(默认)是自动定义的,且不能被改变。
  • 与类不同,结构不能继承其他的结构或类。
  • 结构不能作为其他结构或类的基础结构。
  • 结构可实现一个或多个接口。
  • 结构成员不能指定为 abstractvirtualprotected
  • 当使用 New 操作符创建一个结构对象时,会调用适当的构造函数来创建结构。
  • 与类不同,结构可以不使用 New 操作符即可被实例化。
  • 如果不使用 New 操作符,只有在所有的字段都被初始化之后,字段才被赋值,对象才被使用。

类 vs 结构

类和结构有以下几个基本的不同点:

  • 类是引用类型,结构是值类型(直接在栈上)。
  • 结构不支持继承。
  • 结构不能声明默认的构造函数。

命名空间

namespace namespace_name
{
// 代码声明
}

使用例

using System;
namespace first_space
{
class namespace_cl
{
public void func()
{
Console.WriteLine("Inside first_space");
}
}
}
namespace second_space
{
class namespace_cl
{
public void func()
{
Console.WriteLine("Inside second_space");
}
}
}
class TestClass
{
static void Main(string[] args)
{
first_space.namespace_cl fc = new first_space.namespace_cl();
second_space.namespace_cl sc = new second_space.namespace_cl();
fc.func();
sc.func();
Console.ReadKey();
}
}

C# 预处理器指令

下表列出了 C# 中可用的预处理器指令:

预处理器指令描述
#define它用于定义一系列成为符号的字符。
#undef它用于取消定义符号。
#if它用于测试符号是否为真。
#else它用于创建复合条件指令,与 #if 一起使用。
#elif它用于创建复合条件指令。
#endif指定一个条件指令的结束。
#line它可以让您修改编译器的行数以及(可选地)输出错误和警告的文件名。
#error它允许从代码的指定位置生成一个错误。
#warning它允许从代码的指定位置生成一级警告。
#region它可以让您在使用 Visual Studio Code Editor 的大纲特性时,指定一个可展开或折叠的代码块。
#endregion它标识着 #region 块的结束。

形参的知识

default 关键字

这里的 default 关键字不是指 switch 语句中的那个

默认构造函数是通过 new 运算符来调用的

int myInt = new int();

// default(T)如下所示:
int myInt = default(int);

// 以上语句同下列语句效果相同:
int myInt = 0;

在 C# 中可以使用 struct 来定义数据,而 struct 都需要设置一个默认值,这个 default 就是用来取得这个默认值

形参后面的问号

因为某些 struct 修饰的对象不能为 null,这个问号就是让这个参数可以为 null

而普通用 class 修饰的对象是可以为空的

命名实参和可选实参

命名实参

例如,通过以函数定义的顺序按位置发送实参,可以调用打印订单详细信息(例如卖家姓名、订单号和产品名称)的函数。

PrintOrderDetails("Gift Shop", 31, "Red Mug");

如果不记得形参的顺序,但却知道其名称,则可以按任意顺序发送实参。

PrintOrderDetails(orderNum: 31, productName: "Red Mug", sellerName: "Gift Shop");
PrintOrderDetails(productName: "Red Mug", sellerName: "Gift Shop", orderNum: 31);

可选实参

就是一些参数可以省略,使用的它的默认值(大大的减少了方法重载)

public void ExampleMethod(int required, string optionalstr = "default string",
int optionalint = 10)
anExample.ExampleMethod(3, optionalint: 4);

C# 中的 Lambda

参考资料 => 运算符(C# 参考)

在 C# 中与 Java一样有 Lambda,但是 C# 中的 Lambda 则是真正的匿名函数,而非 Java的那种匿名类,因此使用方式和 Java 也是有一定的区别

语法是同 Java的一致

member => expression;

使用匿名函数重写 ToString() 方法

public override string ToString() => $"{fname} {lname}".Trim();

它是下面这个代码的缩写

public override string ToString()
{
return $"{fname} {lname}".Trim();
}

匿名函数

先来介绍一下 C# 中的匿名函数,可以看到,实际上就是通过委托来完成的

class Test
{
delegate void TestDelegate(string s);
static void M(string s)
{
Console.WriteLine(s);
}

static void Main(string[] args)
{
// Original delegate syntax required
// initialization with a named method.
TestDelegate testDelA = new TestDelegate(M);

// C# 2.0: A delegate can be initialized with
// inline code, called an "anonymous method." This
// method takes a string as an input parameter.
TestDelegate testDelB = delegate(string s) { Console.WriteLine(s); };

// C# 3.0. A delegate can be initialized with
// a lambda expression. The lambda also takes a string
// as an input parameter (x). The type of x is inferred by the compiler.
TestDelegate testDelC = (x) => { Console.WriteLine(x); };

// Invoke the delegates.
testDelA("Hello. My name is M and I write lines.");
testDelB("That's nothing. I'm anonymous and ");
testDelC("I'm a famous author.");

// Keep console window open in debug mode.
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
/* Output:
Hello. My name is M and I write lines.
That's nothing. I'm anonymous and
I'm a famous author.
Press any key to exit.
*/